package com.yunjian.core.busi.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yunjian.core.basic.model.SResource;
import com.yunjian.core.basic.model.SResourceExample;
import com.yunjian.core.basic.model.SRole;
import com.yunjian.core.basic.model.SRoleExample;
import com.yunjian.core.basic.model.SRoleResourceExample;
import com.yunjian.core.basic.model.SRoleResourceKey;
import com.yunjian.core.basic.model.SUserRoleExample;
import com.yunjian.core.basic.model.SUserRoleKey;
import com.yunjian.core.basic.service.SResourceService;
import com.yunjian.core.basic.service.SRoleResourceService;
import com.yunjian.core.basic.service.SRoleService;
import com.yunjian.core.basic.service.SUserRoleService;
import com.yunjian.core.busi.model.EmployeeExample;
import com.yunjian.core.busi.service.EmployeeService;
import com.yunjian.core.busi.service.EmployeeVoService;
import com.yunjian.core.busi.vo.EmployeeVo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *
 * @author tsh721@126.com
 */
@Service
public class EmployeeVoServiceImpl implements EmployeeVoService {

    private final static Logger logger = LoggerFactory.getLogger(EmployeeVoServiceImpl.class);
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private SUserRoleService userRoleService;
    @Autowired
    private SRoleService roleService;
    @Autowired
    private SRoleResourceService roleResourceService;
    @Autowired
    private SResourceService resourceService;

    @Override
    public PageInfo<EmployeeVo> emptyPaged(int page, int rows) {
        PageHelper.startPage(page, rows);
        PageInfo<EmployeeVo> pageInfo = new PageInfo<>(Collections.EMPTY_LIST);
        return pageInfo;
    }
    
    @Override
    public PageInfo<EmployeeVo> selectPagedByExample(int page, int rows, EmployeeExample example) {
        PageHelper.startPage(page, rows);
        PageInfo<EmployeeVo> pageInfo = new PageInfo<>(selectVo(example));
        return pageInfo;
    }

    @Override
    public List<EmployeeVo> selectVo(EmployeeExample example) {
        List<EmployeeVo> result = employeeService.selectVo(example);
        result = fitRole(result);
        return result;
    }

    @Override
    public EmployeeVo selectByPrimaryKey(String userId) {
        EmployeeVo vo = employeeService.selectVoByPrimaryKey(userId);
        List<EmployeeVo> vos = new ArrayList<>(1);
        vos.add(vo);
        fitRole(vos);
        return vo;
    }

    private List<EmployeeVo> fitRole(List<EmployeeVo> employeeVos) {
        if (CollectionUtils.isNotEmpty(employeeVos)) {
            List<String> userIds = new ArrayList<>();
            employeeVos.stream().forEach((employeeVo) -> {
                userIds.add(employeeVo.getUserId());
            });
            SUserRoleExample userRoleExample = new SUserRoleExample();
            userRoleExample.createCriteria().andUserIdIn(userIds);
            List<SUserRoleKey> urList = userRoleService.selectByExample(userRoleExample);
            if (CollectionUtils.isNotEmpty(urList)) {
                //userId, Set<roleId>
                Map<String, Set<String>> urIdMap = new HashMap<>();
                //roleId, role
                Map<String, SRole> roleMap = new HashMap<>();
                //userId, Set<resourceId>
                Map<String, Set<String>> usIdMap = new HashMap<>();
                //resId, resource
                Map<String, SResource> resMap = new HashMap<>();

                List<String> roleIdList = new ArrayList<>();
                urList.stream().forEach((key) -> {
                    if (addtoMap(key, urIdMap)) {
                        roleIdList.add(key.getRoleId());
                    }
                });
                //查询角色
                SRoleExample roleExample = new SRoleExample();
                roleExample.createCriteria().andRoleIdIn(roleIdList);
                List<SRole> roles = roleService.selectByExample(roleExample);
                if (CollectionUtils.isNotEmpty(roles)) {
                    roles.stream().forEach((role) -> {
                        roleMap.put(role.getRoleId(), role);
                    });
                }

                // 查询资源
                SRoleResourceExample rrEx = new SRoleResourceExample();
                rrEx.createCriteria().andRoleIdIn(roleIdList);
                List<SRoleResourceKey> rrList = roleResourceService.selectByExample(rrEx);
                if (CollectionUtils.isNotEmpty(rrList)) {
                    Set<String> resIdSet = new HashSet<>();
                    rrList.stream().forEach((key) -> {
                        addtoMap(key, urIdMap, usIdMap);
                        resIdSet.add(key.getResId());
                    });
                    List<String> resIdList = new ArrayList<>(resIdSet);
                    SResourceExample rEx = new SResourceExample();
                    rEx.createCriteria().andResIdIn(resIdList);
                    rEx.setDistinct(true);
                    List<SResource> resources = resourceService.selectByExample(rEx);
                    if (CollectionUtils.isNotEmpty(resources)) {
                        resources.stream().forEach((res) -> {
                            resMap.put(res.getResId(), res);
                        });
                    }
                }

                employeeVos.stream().forEach((employeeVo) -> {
                    String userId = employeeVo.getUserId();
                    Set<String> roleIdSet = urIdMap.get(userId);
                    if (CollectionUtils.isNotEmpty(roleIdSet)) {
                        List<SRole> roleList = new ArrayList<>();
                        for (String roleId : roleIdSet) {
                            SRole role = roleMap.get(roleId);
                            if (null != role) {
                                roleList.add(role);
                            }
                        }
                        employeeVo.setRoles(roleList);
                    }
                    Set<String> resIdSet = usIdMap.get(userId);
                    if (CollectionUtils.isNotEmpty(resIdSet)) {
                        List<SResource> resList = new ArrayList<>();
                        for (String resId : resIdSet) {
                            SResource resource = resMap.get(resId);
                            if (null != resource) {
                                resList.add(resource);
                            }
                        }
                        employeeVo.setResources(resList);
                    }
                });
            }
        }
        return employeeVos;
    }

    private boolean addtoMap(SUserRoleKey key, Map<String, Set<String>> urIdMap) {
        Set<String> set = urIdMap.get(key.getUserId());
        if (null == set) {
            set = new HashSet<>();
            urIdMap.put(key.getUserId(), set);
        }
        return set.add(key.getRoleId());
    }

    private void addtoMap(SRoleResourceKey key, Map<String, Set<String>> urIdMap, Map<String, Set<String>> usIdMap) {
        key.getResId();
        for (Map.Entry<String, Set<String>> entry : urIdMap.entrySet()) {
            String userId = entry.getKey();
            Set<String> roleIdSet = entry.getValue();
            if (roleIdSet.contains(key.getRoleId())) {
                addtoMap(userId, key.getResId(), usIdMap);
            }
        }
    }

    private void addtoMap(String userId, String resId, Map<String, Set<String>> usIdMap) {
        Set<String> set = usIdMap.get(userId);
        if (null == set) {
            set = new HashSet<>();
            usIdMap.put(userId, set);
        }
        set.add(resId);
    }
}
